package com.kg.fiber.service.clock;

import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import org.apache.commons.io.IOUtils;

import com.google.common.base.Preconditions;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

public class ClockDriver {
	
	private static RandomAccessFile file = null;
	
	private static byte[] read() throws Exception {
		
		initialize();
		
		Preconditions.checkState(ready(), "Clock device is not ready!");
				
		byte[] b = new byte[16];
		file.readFully(b);
		return b;
	}
	
	public static void initialize() {
		
		if(!ready())  {
			try {
				file = new RandomAccessFile("/dev/pci_szk","r");
			} catch (FileNotFoundException e) {
			}
		} 		
	}
	
	public static void terminate() {
		IOUtils.closeQuietly(file);
		file = null;
	}
	
	public static boolean ready() {
		return file != null;
	}
	
	public static Time now() throws Exception {
		
		byte[] b = read();
		
		Time ts = Time.from(b);

		return ts;
		
	}
	
	
	
	public static Time defaultTime = new Time();
	
	@NoArgsConstructor
	public static class Time {
		@Getter @Setter
		private int year;
		@Getter @Setter
		private int month;
		@Getter @Setter
		private int day;
		@Getter @Setter
		private int hour;
		@Getter @Setter
		private int minute;
		@Getter @Setter
		private int second;
		@Getter @Setter
		private int millisecond;
		@Getter @Setter
		private boolean master;
		@Getter @Setter
		private boolean gps;
		@Getter @Setter
		private int stn;
		@Getter @Setter
		private int quality;
		
		private long timestamp = 0L;
				
		public String datetime() {
			return String.format("%04d-%02d-%02d %02d:%02d:%02d.%03d", 
					year, month, day, hour, minute, second, millisecond);
		}
		
		public long getTimestamp() {
			
			if(timestamp == 0) {
				Calendar.Builder cb = new Calendar.Builder();
				cb.setFields(
						Calendar.YEAR, year,
						Calendar.MONTH, month - 1,
						Calendar.DAY_OF_MONTH, day,
						Calendar.HOUR_OF_DAY, hour,
						Calendar.MINUTE, minute,
						Calendar.SECOND, second,
						Calendar.MILLISECOND, millisecond);
				timestamp = cb.build().getTimeInMillis();
			}
			
			return timestamp;
			/*
			try {
				return sdf.parse(datetime()).getTime();
			} catch(Exception e) {
				return 0L;
			}
			*/
		}
		
		public static Time from(byte[] b) {
			if(b == null) return null;
			Time ts = new Time();
			ts.setYear((b[9] & 0xFF) * 100 + (b[8] & 0xFF));
			ts.setMonth(b[7]&0xFF);
			ts.setDay(b[6]&0xFF);
			ts.setHour(b[5]&0xFF);
			ts.setMinute(b[4]&0xFF);
			ts.setSecond(b[3]&0xFF);
			ts.setMillisecond(((((b[1]&0xFF) << 8) + (b[2]&0xFF))<<1)/10);
			
			ts.setGps((b[0]&0x01)==0);
			ts.setMaster((b[0]&0x80)!=0);
			ts.setStn(b[10] & 0xFF);
			ts.setQuality(b[11] & 0xFF);
			return ts;
		}
		
		
		
		public int compare(Time tm) {
			int r;
			
			r = Integer.compare(this.year, tm.year);
			if(r != 0) return r;
			
			r = Integer.compare(this.month, tm.month);
			if(r != 0) return r;
			
			r = Integer.compare(this.day, tm.day);
			if(r != 0) return r;
			
			r = Integer.compare(this.hour, tm.hour);
			if(r != 0) return r;
			
			r = Integer.compare(this.minute, tm.minute);
			if(r != 0) return r;
			
			r = Integer.compare(this.second, tm.second);
			if(r != 0) return r;
			
			r = Integer.compare(this.millisecond, tm.millisecond);
			if(r != 0) return r;
			
			return 0;
		}
	}
	
	
	public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");


}
